﻿#include "libsshUtils.h"
#include <QThread>
#include <QMutex>
#include <QCoreApplication>
#include <QFile>
#include <QFileInfo>
#include <QDateTime>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#include <QDataStream>
#include <QMessageBox>
#include <QMetaType>
#include <QCollator>
#include <QDebug>
#undef print
#define print qDebug()
const unsigned char modes[] = {
        60, 0, 0, 0, 1,//支持ctrl +c 字符打印
        /* enable OCRNL */
//        73, 0, 0, 0, 0,
//        /* disable all other CR/NL handling */
//        34, 0, 0, 0, 0,
//        35, 0, 0, 0, 0,
//        36, 0, 0, 0, 0,
//        72, 0, 0, 0, 0,
//        74, 0, 0, 0, 0,
//        75, 0, 0, 0, 0,
        0, /* TTY_OP_END */
    };

QMutex libssh2Mutex;
libsshUtils::libsshUtils(QObject *parent,libsshParams *params):QThread{parent},sshParams(params)
{
    sendDataByte.clear();
    downloadListPath.clear();
    initFlag=false;
    session=nullptr;
    qRegisterMetaType<QList<libsshSftpFileInfo>>("QList<libsshSftpFileInfo>");
    connect(this,&libsshUtils::sessionStateSignal,this,&libsshUtils::sshConnectStateSlots,Qt::QueuedConnection);
}

libsshUtils::~libsshUtils()
{
    emit sessionStateSignal(libsshUtils::DISCONNECTED);
    if(sshParams)
    {
        sshParams->deleteLater();
        sshParams=nullptr;
    }
    if(session)
    {
        ssh_free(session);
        session = nullptr;
    }
}

void libsshUtils::disconnectSSH()
{
    QList<libsshSftpFileInfo> listInfo;
    if(channel)
    {
        ssh_channel_close(channel);
        ssh_channel_free(channel);
    }

    channel = NULL;
    if(sftp)
        sftp_free(sftp);
    sftp=NULL;
    if(session)
    {
        ssh_disconnect(session);
        ssh_free(session);
    }
    listInfo.clear();
    emit sftpDirChangedSignal(listInfo);
    session=NULL;
    emit sessionStateSignal(libsshUtils::DISCONNECTED);
}

void libsshUtils::connectSSh()
{
    qDebug()<<"initializeFunction()"<< QThread::currentThread();
    if(!this->sshParams)
    {
        emit sftpErrorMsgSignal(tr("Connect params is error!"));
        return;
    }
    switch(this->sshParams->authenticationType)
    {
    case libsshParams::AuthenticationTypePassword:
        break;
    case libsshParams::AuthenticationTypePublicKey:
        break;
    case libsshParams::AuthenticationTypeKeyboardInteractive:
        break;

        // Some servers disable "password", others disable "keyboard-interactive".
    case libsshParams::AuthenticationTypeTryAllPasswordBasedMethods:
        break;
    }

    //ssh_threads_set_callbacks(ssh_threads_get_pthread());

    session = ssh_new();
    ssh_options_set(session, SSH_OPTIONS_USER, sshParams->userName.toLatin1().data());

    ssh_options_set(session, SSH_OPTIONS_HOST, sshParams->host.toLatin1().data());
    int port=sshParams->port;
    ssh_options_set(session, SSH_OPTIONS_PORT, &port);
    int verbosity = 1;
    ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
    int rc = ssh_connect(session);

    if (rc != SSH_OK) {
        qDebug() << "Connection to host failed!";
        ssh_free(session);
        emit errorMsgSignal("Connection to host failed!");
        // char * msg = "\r\nFail to connect to server, press enter to restart ...";
        // emit dispatchData(msg, strlen(msg));
        // emit sessionError(1);
        return;
    }


    int method;
    char password[128] = {0};
    // Try to authenticate
    rc = ssh_userauth_none(session, NULL);
    if (rc == SSH_AUTH_ERROR) {
        print<<"userName error";
        ssh_disconnect(session);
        ssh_free(session);
        emit errorMsgSignal("Connection to host failed!");
        return ;
    }

    method = ssh_userauth_list(session, NULL);
    qDebug() << "debug method" << method;
    while (rc != SSH_AUTH_SUCCESS) {
        QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
        // char *passwd = "Password: \r\n";
        // emit dispatchData(passwd, strlen(passwd));

        // Try to authenticate with password
        if (method & SSH_AUTH_METHOD_PASSWORD) {
            //if (!qterm->siteInfo.password.isNull()) {
            // print<<sshParams->passWord;
            QByteArray pw = sshParams->passWord.toLatin1();
            rc = ssh_userauth_password(session, NULL, pw.data());
            // }
            if (rc == SSH_AUTH_ERROR) {
                emit errorMsgSignal(ssh_get_error(session));
                return ;
            } else if (rc == SSH_AUTH_SUCCESS) {
                break;
            }
        }
        memset(password, 0, sizeof(password));
        if (method & SSH_AUTH_METHOD_GSSAPI_MIC){
            rc = ssh_userauth_gssapi(session);
            if(rc == SSH_AUTH_ERROR) {
                emit errorMsgSignal(ssh_get_error(session));
                return ;
            } else if (rc == SSH_AUTH_SUCCESS) {
                break;
            }
        }
        // Try to authenticate with public key first
        if (0) {
            if (method & SSH_AUTH_METHOD_PUBLICKEY) {
                ssh_key privkey;
                if(ssh_pki_import_privkey_file("",NULL,
                                               NULL,NULL,&privkey) == SSH_OK)
                {
                    rc = ssh_userauth_publickey(session, NULL, privkey);
                }
                ssh_key_free(privkey);
                //rc = ssh_userauth_publickey_auto(session, NULL, NULL);
                if (rc == SSH_AUTH_ERROR) {
                    emit errorMsgSignal(ssh_get_error(session));
                    return ;
                } else if (rc == SSH_AUTH_SUCCESS) {
                    break;
                }
            }
        }
        // Try to authenticate with keyboard interactive";
        if (method & SSH_AUTH_METHOD_INTERACTIVE) {
            rc = authenticate_kbdint(session, NULL);
            if (rc == SSH_AUTH_ERROR) {
                emit errorMsgSignal(ssh_get_error(session));
                return ;
            } else if (rc == SSH_AUTH_SUCCESS) {
                break;
            }
        }
    }
    this->channel = ssh_channel_new(session);
    ssh_channel_accept_x11(channel, 10);
    if(ssh_channel_open_session(channel)){
        QString error = QString::asprintf("error opening channel : %s\n",ssh_get_error(session));
        print<<error;
        emit errorMsgSignal(error);
        return;
    }
    //ssh_channel_request_pty_size(channel, "xterm-256color", 80, 25);
    ssh_channel_request_pty_size_modes(channel, "xterm-256color", 80, 25, modes, sizeof(modes));
    if(ssh_channel_request_shell(channel)){
        QString error =QString::asprintf("Requesting shell : %s\n",ssh_get_error(session));
        print<<error;
        emit errorMsgSignal(error);
        return;
    }
    
    emit sessionStateSignal(libsshUtils::CONNECTED);
}

void libsshUtils::sshConnectStateSlots(bool state)
{
    if(state==libsshUtils::CONNECTED)
    {
        if(!session)
            return;
         socket_t socket = ssh_get_fd(session);

         read_notifier = new QSocketNotifier(socket,
                                             QSocketNotifier::Read,
                                             this);
         read_notifier->setEnabled(true);
         connect(read_notifier, SIGNAL(activated(int)),
                 this, SLOT(select_loop()));
#if 0
         sftp_connect();


         emit sftpSetCurrentPathSignal("/home/"+sshParams->userName);
         sftp_list_dir_slots("/home/"+sshParams->userName);
#endif
         initFlag=true;
         ssh_channel_set_blocking(channel,false);
         //disconnect();
         emit sshConnectedSignal();
    }
    else
    {
        emit errorMsgSignal("ssh disconnected!\r\n");
    }
}

void libsshUtils::run()
{
    //
#define BUFSIZE 32000

    char *buffer=nullptr;
    int nbytes = 0;
   //while (1)
    {
        /* code */
    
    //QCoreApplication::processEvents();
    if(!session)
    {
        if(!ssh_is_connected(session))
        {
            connectSSh();
        }
    }
    if(session)
    {
        if(ssh_is_connected(session))
        {
            //libssh2Mutex.lock();
            int ret = ssh_channel_poll(channel,false);
            if(ret==SSH_EOF||ret == SSH_ERROR|| ret==0)
            {

            }
            else
            {
                buffer = new char[ret+1];
                if(buffer)
                {
                    while(1)
                    {
                        nbytes = ssh_channel_read(channel,buffer,ret,false);
                         if (nbytes >0)
                        {
                            QByteArray data = QByteArray(buffer,nbytes);
                            //print<<data;
                            emit receiveData(data);
                            break;
                        }
                        else if(nbytes==SSH_AGAIN)
                        {

                        }
                        else if(nbytes==SSH_ERROR||nbytes==SSH_EOF)
                        {
                            break;
                        }
                    }
                    if(buffer)
                     {
                        delete[] buffer;
                        buffer=nullptr;
                    }
                }
            }
            //libssh2Mutex.unlock();
        }
#if 0
        if(downloadListPath.count()>0)
        {
            downLoadFile(downloadListPath);
            downloadListPath.clear();
        }
        if(uploadListPath.count()>0)
        {
            upLoadFile(uploadListPath);
            uploadListPath.clear();
        }
#endif
    }
}
}

int libsshUtils::authenticate_kbdint(ssh_session session, const char *password) {
    int err;

    err = ssh_userauth_kbdint(session, NULL, NULL);
    while (err == SSH_AUTH_INFO) {
        const char *instruction;
        const char *name;
        char buffer[128];
        int i, n;

        name = ssh_userauth_kbdint_getname(session);
        instruction = ssh_userauth_kbdint_getinstruction(session);
        n = ssh_userauth_kbdint_getnprompts(session);

        if (name && strlen(name) > 0) {
            print<<QString::asprintf("%s\n", name);
            emit receiveData(QString::asprintf("%s\n", name).toLatin1());
        }

        if (instruction && strlen(instruction) > 0) {
            print<<QString::asprintf("%s\n", instruction);
            emit receiveData(QString::asprintf("%s\n", instruction).toLatin1());
        }

        for (i = 0; i < n; i++) {
            const char *answer;
            const char *prompt;
            char echo;

            prompt = ssh_userauth_kbdint_getprompt(session, i, &echo);
            if (prompt == NULL) {
                emit errorMsgSignal(ssh_get_error(session));
                break;
            }

            if (echo) {
                char *p;

                print<<QString::asprintf("%s", prompt);
                emit receiveData(QString::asprintf("%s", prompt).toLatin1());
                if (fgets(buffer, sizeof(buffer), stdin) == NULL) {
                    emit errorMsgSignal(ssh_get_error(session));
                    return SSH_AUTH_ERROR;
                }

                buffer[sizeof(buffer) - 1] = '\0';
                if ((p = strchr(buffer, '\n'))) {
                    *p = '\0';
                }
                emit receiveData(QString::asprintf("%s\n", buffer).toLatin1());
                if (ssh_userauth_kbdint_setanswer(session, i, buffer) < 0) {
                    emit errorMsgSignal(ssh_get_error(session));
                    return SSH_AUTH_ERROR;
                }

                memset(buffer, 0, strlen(buffer));
            } else {
                if (password && strstr(prompt, "Password:")) {
                    answer = password;
                } else {
                    buffer[0] = '\0';

                    if (ssh_getpass(prompt, buffer, sizeof(buffer), 0, 0) < 0) {
                        emit errorMsgSignal(ssh_get_error(session));
                        return SSH_AUTH_ERROR;
                    }
                    answer = buffer;
                }
                err = ssh_userauth_kbdint_setanswer(session, i, answer);
                memset(buffer, 0, sizeof(buffer));
                if (err < 0) {
                    emit errorMsgSignal(ssh_get_error(session));
                    return SSH_AUTH_ERROR;
                }
            }
        }
        err=ssh_userauth_kbdint(session,NULL,NULL);
    }

    return err;
}

void libsshUtils::initializeFunction()
{
    //connectSSh();
    this->start();
}

void libsshUtils::select_loop(){
    this->start();
}

void libsshUtils::sendData(QByteArray data){
    if(data.count()==1&&data.at(0)=='\r')
    {
        ssh_channel_write(channel,"\n",1);
    }
    else
    {
        ssh_channel_write(channel,data.data(),data.count());
    }
}

//重新连接服务器
bool libsshUtils::reConnectTcpServer()
{
    ssh_connect(session);
    return true;
}

int libsshUtils::getConnectStatus()
{
    return 0;
}

#if 0
void libsshUtils::sftp_connect()
{
    sftp = sftp_new(session);
    if (!sftp) {
        emit sftpErrorMsgSignal(ssh_get_error(session));
        return;
    }

    if (sftp_init(sftp)) {
        emit sftpErrorMsgSignal(ssh_get_error(session));
        sftp_free(sftp);
        return;
    }
    return;
}

QString libsshUtils::getType(uint32_t permissions)
{
    QString type="";
    bool ok=false;
    uint32_t per = QString::asprintf("%.8o",permissions).toUInt(&ok,8);
    if(per&SSH_S_IFSOCK)
        type="s";
    else if(per&SSH_S_IFLNK)
        type="l";
    else if(per&SSH_S_IFREG)
        type="-";
    else if(per&SSH_S_IFBLK)
        type="b";
    else if(per&SSH_S_IFDIR)
        type="d";
    else if(per&SSH_S_IFCHR)
        type="c";
    else if(per&SSH_S_IFIFO)
        type="f";
    return type;
}

QString libsshUtils::getPermission(uint32_t permissions)
{
    QString type="";

    type = getType(permissions);

    if(permissions&READ_USER)
        type+="r";
    else
        type+="-";
    if(permissions&WRITE_USER)
        type+="w";
    else
        type+="-";
    if(permissions&EXE_USER)
        type+="x";
    else
        type+="-";
    if(permissions&READ_GROUP)
        type+="r";
    else
        type+="-";
    if(permissions&WRITE_GROUP)
        type+="w";
    else
        type+="-";
    if(permissions&EXE_GROUP)
        type+="x";
    else
        type+="-";
    if(permissions&READ_OTHER)
        type+="r";
    else
        type+="-";
    if(permissions&WRITE_OTHER)
        type+="w";
    else
        type+="-";
    if(permissions&EXE_OTHER)
        type+="x";
    else
        type+="-";
    return type;
}

QString libsshUtils::getSize(quint64 size)
{
    QString sizeText="";
    if(size<1024)
        sizeText= QString::asprintf("%lldB",size);
    else if(size>=1024&&size<1024*1024)
        sizeText= QString::asprintf("%0.1fKB",size/1024.0);
    else if(size>=1024*1024&&size<1024*1024*1024)
        sizeText= QString::asprintf("%0.1fMB",size/1024.0/1024.0);
    else
        sizeText= QString::asprintf("%0.1fGB",size/1024.0/1024.0/1024.0);
    return sizeText;
}

void libsshUtils::sftp_list_dir_slots(QString path)
{
    sftp_dir dir;
    sftp_attributes attributes;
    int rc;
    QDateTime datetime;
    this->currentPath = path;
    dir = sftp_opendir(sftp, path.toLatin1().data());
    if (!dir)
    {
        emit sftpErrorMsgSignal( QString::asprintf( "Directory not opened: %s\n",
                                                   ssh_get_error(session)));
        return ;
    }
    listInfo.clear();
    while ((attributes = sftp_readdir(sftp, dir)) != NULL)
    {
        QString fileInfo=  QString::asprintf("%-20s %10llu %.8o %s(%d)\t%s(%d) type:%d\n",
                                             attributes->name,
                                             (long long unsigned int) attributes->size,
                                             attributes->permissions,
                                             attributes->owner,
                                             attributes->uid,
                                             attributes->group,
                                             attributes->gid,
                                             attributes->type);
        libsshSftpFileInfo info;
      //  print << fileInfo;
        info.name = QString::asprintf("%s",attributes->name);
        //info.permission = getPermission(attributes->permissions);
        info.permission = QString::asprintf("%s",attributes->longname).split(' ').at(0);
        info.size = getSize(attributes->size);
        info.group = QString::asprintf("%s",attributes->group);
        info.owner = QString::asprintf("%s",attributes->owner);
        info.modifyTime = datetime.fromMSecsSinceEpoch(attributes->mtime).toString("yyyy/MM/dd hh:mm:ss");
        info.type   = QString::asprintf("%s",attributes->longname).split(' ').at(0).data()[0];
        if(info.type=="l")
        {
            QString dirlink = path+info.name;
            sftp_attributes dirlinkattributes = sftp_stat(sftp,dirlink.toLatin1().data());
            if(dirlinkattributes)
            {
                QString type  = getType(dirlinkattributes->permissions);
                if(type!=info.type &&type=="d")
                {
                    info.dirLink=true;
                }
                sftp_attributes_free(attributes);
            }
        }
        listInfo.append(info);
        sftp_attributes_free(attributes);
    }
    if (!sftp_dir_eof(dir))
    {
        emit sftpErrorMsgSignal(  QString::asprintf("Can't list directory: %s\n",
                                                   ssh_get_error(session)));
        sftp_closedir(dir);
        return ;
    }
    emit sftpDirChangedSignal(listInfo);
    rc = sftp_closedir(dir);
    if (rc != SSH_OK)
    {
        emit sftpErrorMsgSignal( QString::asprintf("Can't close directory: %s\n",
                                                  ssh_get_error(session)));
        return ;
    }
    return ;
}

int libsshUtils::download(QString path)
{
    int concurrent_downloads = 8;
    //struct timestamp_struct ts = {0};
    float ms = 0.0f;

    int warned = 0, i, rc;
    float bps ;

    quint64 blockSize=sizeof(this->buffer);
    sftp_file file=NULL;
    quint64 bytes;
    quint64 total=0;
    int r;
    unsigned long toread;
    int *ids=NULL;
    sftp_attributes attributes=NULL;
    QFileInfo qfileinfo = QFileInfo(path);
    QFile *qfile = new QFile(this->localSavePath+"/"+qfileinfo.fileName());
    attributes = sftp_stat(sftp,path.toLatin1().data());
    if(attributes)
    {
        bytes = attributes->size;
        sftp_attributes_free(attributes);
    }
    else
    {
        print<<__FUNCTION__<<__LINE__<<path;
        goto error;
    }
    file = sftp_open(sftp,path.toLatin1().data(), O_RDWR, S_IRWXU);
    if (file == NULL) {
        print<<__FUNCTION__<<__LINE__<<path;
        goto error;
    }
    ids = (int*)malloc(concurrent_downloads * sizeof(int));
    if (ids == NULL) {
        print<<__FUNCTION__<<__LINE__;
        goto error;
    }
    for (i=0;i<concurrent_downloads;++i){
        ids[i]=sftp_async_read_begin(file, blockSize);
        if(ids[i]==SSH_ERROR)
        {
            print<<__FUNCTION__<<__LINE__;
            goto error;
        }

    }
    qfile->open(QIODevice::ReadWrite|QIODevice::Truncate);
    if(!qfile->isOpen())
    {
        emit sftpErrorMsgSignal(tr("File open failed!"));
        goto error;
    }
    print<<__FUNCTION__<<__LINE__<<path;
    i=0;
    ms = QDateTime::currentMSecsSinceEpoch();
    print<<__FUNCTION__<<__LINE__<<ms;
    while(total < bytes){
        memset(buffer,0,sizeof(buffer));
        r = sftp_async_read(file, buffer, blockSize, ids[i]);
        if(r == SSH_ERROR)
        {
            print<<__FUNCTION__<<__LINE__;
            goto error;
        }
        //print<<"read"<<QString::asprintf("%s",buffer);
        qfile->write(buffer,r);
        qfile->flush();
        total += r;
        emit sftpDownLoadSizeSignal(path,bytes,total);
        if(r != (int)blockSize && total != bytes && !warned){
            print<<QString::asprintf("async_sftp_download : receiving short reads (%d, requested %llu) "
                                     "the received file will be corrupted and shorted. Adapt chunksize to %d\n",
                                     r, blockSize,r);
            warned = 1;
        }
        /* we had a smaller file */
        if(r==0){
            print<<QString::asprintf("File smaller than expected : %llu (expected %llu).\n",total,bytes);
            bytes = total;
            break;
        }
        toread = bytes - total;
        if(toread < blockSize * concurrent_downloads){
            /* we've got enough launched downloads */
            ids[i]=-1;
        }
        if(toread > blockSize)
            toread = blockSize;
        ids[i]=sftp_async_read_begin(file,toread);
        if(ids[i] == SSH_ERROR)
        {
            print<<__FUNCTION__<<__LINE__;
            goto error;
        }
        i = (i+1) % concurrent_downloads;
    }
    sftp_close(file);
    ms = QDateTime::currentMSecsSinceEpoch()-ms;
     print<<__FUNCTION__<<__LINE__<<QDateTime::currentMSecsSinceEpoch()<<ms;
    bps=8000 * (float)bytes / ms;
    emit sftpDownLoadFinished(path);
    print<<QString::asprintf("download took %f ms for %llu bytes, at %f bps\n",ms,
                             bytes,bps);
    free(ids);
    if(qfile->isOpen())
    {
        qfile->flush();
        qfile->close();
        qfile->deleteLater();
    }

    return 0;

error:
    rc = ssh_get_error_code(session);
    if (rc != SSH_NO_ERROR) {
        QString errormsg = QString::asprintf("Error during sftp download: %s\n",
                                   ssh_get_error(session));
        print << errormsg;
        emit sftpErrorMsgSignal(errormsg);
    }
    if(file)
        sftp_close(file);
    free(ids);
    if(qfile->isOpen())
    {
        qfile->flush();
        qfile->close();
        qfile->deleteLater();
    }
    return -1;
}

int libsshUtils::downLoadFile(QStringList pathList)
{
    for(int m=0;m<pathList.count();m++)
    {
        download(pathList.at(m));
    }
    return 0;
}

int libsshUtils::upload(QString path)
{
    float ms = 0.0f;

    int  rc;
    float bps ;

    quint64 blockSize=sizeof(this->buffer);
    sftp_file file=NULL;
    quint64 bytes;
    quint64 total=0;
    QFileInfo qfileinfo = QFileInfo(path);
    QFile *qfile = new QFile(path);
    QString remotePath = this->currentPath+"/"+qfileinfo.fileName();
    print<<__FUNCTION__<<__LINE__<<remotePath;
    QDataStream stream;
    bytes = qfileinfo.size();
    file = sftp_open(sftp,remotePath.toLatin1().data(), O_RDWR|O_TRUNC|O_CREAT, 0777);
    if (file == NULL) {
        print<<__FUNCTION__<<__LINE__<<path;
        goto error;
    }

    qfile->open(QIODevice::ReadOnly);
    if(!qfile->isOpen())
    {
        emit sftpErrorMsgSignal(tr("File open failed!"));
        goto error;
    }
    print<<__FUNCTION__<<__LINE__<<path;
    ms = QDateTime::currentMSecsSinceEpoch();
    print<<__FUNCTION__<<__LINE__<<ms;

    stream.setDevice(qfile);
    while(total < bytes){
        quint64 towrite = bytes - total;
        int w;
        if(towrite > blockSize)
            towrite = blockSize;
        int len = stream.readRawData(buffer,sizeof(buffer));
        if(len<0)
        {
            print<<__FUNCTION__<<__LINE__<<len;
            emit sftpDownLoadSizeSignal(path,bytes,total);
            break;
        }
        w=sftp_write(file,buffer,len);
        if(w == SSH_ERROR)
            goto error;
        total += w;
        emit sftpDownLoadSizeSignal(path,bytes,total);
    }
    emit sftpDownLoadFinished(path);
    sftp_close(file);
    ms = QDateTime::currentMSecsSinceEpoch()-ms;
     print<<__FUNCTION__<<__LINE__<<QDateTime::currentMSecsSinceEpoch()<<ms;
    bps=8000 * (float)bytes / ms;
    emit sftpDownLoadFinished(path);
    print<<QString::asprintf("download took %f ms for %llu bytes, at %f bps\n",ms,
                             bytes,bps);

    if(qfile->isOpen())
    {
        qfile->flush();
        qfile->close();
        qfile->deleteLater();
    }
    return 0;

error:
    rc = ssh_get_error_code(session);
    if (rc != SSH_NO_ERROR) {
        QString errormsg = QString::asprintf("Error during sftp upload: %s\n",
                                   ssh_get_error(session));
        print << errormsg;
        emit sftpErrorMsgSignal(errormsg);
    }
    if(file)
        sftp_close(file);
    if(qfile->isOpen())
    {
        qfile->flush();
        qfile->close();
        qfile->deleteLater();
    }
    return -1;
}

int libsshUtils::upLoadFile(QStringList path)//上传文件
{
    for(int m=0;m<path.count();m++)
    {
        upload(path.at(m));
    }
    return 0;
}

void libsshUtils::startDownLoadFile(QStringList path,QString localSavePath)
{
    downloadListPath = path;
    this->localSavePath = localSavePath;
    print<<__FUNCTION__<<path<<localSavePath<<"12"<<downloadListPath;
    this->start();
}

void libsshUtils::startUpLoadFile(QStringList path)
{
    QString remoteSavePath = this->currentPath;
    uploadListPath = path;
    this->start();
}

void libsshUtils::sftpGetCurrentPathSlot()
{
    int rc;
    char buf[1024]={0};
    if(!session)
        return;
    if(!ssh_is_connected(session))
        return;
    if(!sftp)
        return;
    libssh2Mutex.lock();
    rc = ssh_channel_request_exec(channel, "pwd");
    if (rc < 0) {
        libssh2Mutex.unlock();
        return;
    }
    int rbytes = ssh_channel_read(channel, buf, sizeof(buf), 0);
    if (rbytes <= 0) {
        libssh2Mutex.unlock();
        return;
    }
    libssh2Mutex.unlock();
    QString path = QString::asprintf("%s",buf);
    print<< path;
    emit sftpSetTrackCurrentPathSignal(path);
}

void libsshUtils::sftpRenameFileSlots(QString oldPath,QString newPath)//重命名文件
{
    if(!session)
        return;
    if(!ssh_is_connected(session))
        return;
    if(!sftp)
        return;
    print<<__FUNCTION__<<oldPath<<newPath;
    int rc = sftp_rename(sftp,oldPath.toLatin1().data(),newPath.toLatin1().data());
    if (rc < 0) {
        QString errormsg = QString::asprintf("%s\n",ssh_get_error(session));

        emit sftpErrorMsgSignal(errormsg);
        return;
    }
    sftp_list_dir_slots(this->currentPath);
}

void libsshUtils::sftpMkdirDirSlots(QString newFileDirPath,quint32 permission,bool openDir)//新建目录
{
    if(!session)
        return;
    if(!ssh_is_connected(session))
        return;
    if(!sftp)
        return;
    print<<__FUNCTION__<<newFileDirPath;
    int rc = sftp_mkdir(sftp,newFileDirPath.toLatin1().data(),permission);
    if (rc < 0) {
        QString errormsg = QString::asprintf("%s\n",ssh_get_error(session));

        emit sftpErrorMsgSignal(errormsg);
        return;
    }
    if(openDir)
        this->currentPath= newFileDirPath;//打开新目录
    sftp_list_dir_slots(this->currentPath);
}

void libsshUtils::sftpRemoveSlots(QString path)//删除目录或文件
{
    int rc = 0;
    if(!session)
        return;
    if(!ssh_is_connected(session))
        return;
    if(!sftp)
        return;
    print<<__FUNCTION__<<path;
    sftp_attributes attributes=NULL;
    attributes = sftp_stat(sftp,path.toLatin1().data());
    if(attributes)
    {
        if(attributes->type==SSH_FILEXFER_TYPE_REGULAR)
        {
            QString ccc = QString(tr("Are you sure to delete file %1?")).arg(path);
            int ret = QMessageBox::warning(nullptr,tr("Delete item"),
                    ccc,
                    QMessageBox::Ok | QMessageBox::Cancel);
            switch (ret) {
                case QMessageBox::Ok:
                    rc = sftp_unlink(sftp,path.toLatin1().data());
                    break;
                case QMessageBox::Cancel:
                    // Cancel was clicked
                    break;
                default:
                    // should never be reached
                    break;
            }

        }
        else if(attributes->type==SSH_FILEXFER_TYPE_DIRECTORY)
        {
            QString ccc = QString(tr("Are you sure to delete dir %1?")).arg(path);
            int ret = QMessageBox::warning(nullptr,tr("Delete item"),
                    ccc,
                    QMessageBox::Ok | QMessageBox::Cancel);
            switch (ret) {
                case QMessageBox::Ok:
                    rc = sftp_rmdir(sftp,path.toLatin1().data());
                    break;
                case QMessageBox::Cancel:
                    // Cancel was clicked
                    break;
                default:
                    // should never be reached
                    break;
            }

        }
        sftp_attributes_free(attributes);
    }
    else
    {
        QString errormsg = QString::asprintf("%s\n",ssh_get_error(session));

        emit sftpErrorMsgSignal(errormsg);
        return;
    }
    if (rc < 0) {
        QString errormsg = QString::asprintf("%s\n",ssh_get_error(session));

        emit sftpErrorMsgSignal(errormsg);
        return;
    }
    sftp_list_dir_slots(this->currentPath);
}

void libsshUtils::sftpNewFileSlots(QString newFileName,quint32 permission)
{
    sftp_file file=NULL;
    if(!session)
        return;
    if(!ssh_is_connected(session))
        return;
    if(!sftp)
        return;
    QString path = newFileName;
    print<<__FUNCTION__<<newFileName<<permission;
    file = sftp_open(sftp,path.toLatin1().data(), O_RDWR|O_TRUNC|O_CREAT, permission);
    if (file == NULL) {
        print<<__FUNCTION__<<__LINE__<<path;
        QString errormsg = QString::asprintf("%s\n",ssh_get_error(session));

        emit sftpErrorMsgSignal(errormsg);
        return;
    }
    if(file)
        sftp_close(file);
    sftp_list_dir_slots(this->currentPath);
}
#endif
void libsshUtils::sshResizeWindowSlots(int height,int witdh)
{
    if(!session)
        return;
    if(!ssh_is_connected(session))
        return;
    if(!channel)
        return;
    if(!ssh_channel_is_open(channel))
        return;
    if(row != height || col != witdh)
    {
        row = height;
        col = witdh;
        ssh_channel_change_pty_size(channel, witdh,height);
    }
    
}




